from flask import Blueprint, render_template, current_app, jsonify, request
from sqlalchemy.sql import text
from sqlalchemy import func
from exts import db
from models import Patient, Image
from decorators import *
from .forms import ImageForm, IdForm
from uuid import uuid4
import os
import traceback
import sys
sys.path.insert(0,'dual_env')
# from single_env.single_pre import getpredict as s_pre
# from dual_env.dual_pre import getpredict as d_pre

bp = Blueprint('image', __name__, url_prefix='/image')
# 模型列表，用作model_kind字段的映射
MODEL_LIST = ['deeplabv3+', 'manet', 'mocov2', 'pixprosw', 'pspnet', 'simclr', 'unet', 'unet++']

# 查看标注图片 页面
@bp.route('/show_result')
@login_required
def show_result():
    form = IdForm(request.args)
    if form.validate():
        id = form.id.data
        image = Image.query.get(id)
    else:
        return "发生错误，请刷新页面重试"
    return render_template('show_result.html', image=image)

# 单分辨率 标注 页面
@bp.route('/solo_mark')
@login_required
def solo_mark():
    patient_list = getPatientNameList()
    return render_template('solo_mark.html', patient_list=patient_list)

# 多分辨率 标注 页面
@bp.route('/multi_mark')
@login_required
def multi_mark():
    patient_list = getPatientNameList()
    return render_template('multi_mark.html', patient_list=patient_list)

# 执行单分辨率标注
@bp.route('/solo_transfer', methods=['POST'])
@login_required_ajax
def solo_transfer():
    form = ImageForm(request.form)
    file = request.files.get('file')
    if not form.validate():
        return {'success': False, 'msg': '数据格式有误，请检查后重试'}
    if not check_img(file):
        return {'success': False, 'msg': '图片有误，请检查后重试'}
    image_id = 0
    type = 1
    patient_id = form.patient_id.data
    model_kind = form.model_kind.data
    pre_path = save_img(file)
    try:
        operator_id = g.user.id
        # 调用模型
        # pre_address_1, post_address = s_pre(str(operator_id), str(patient_id), pre_path,
        #                                     MODEL_LIST[model_kind - 1])
        # 在这调用模型
        pre_address_1 = pre_path
        post_address = pre_path
        # 统一路径格式
        pre_address_1 = pre_address_1.replace('\\', '/')
        post_address = post_address.replace('\\', '/')
        # 存数据库前把前缀删掉
        str_d = 'static/'
        pre_address_1 = pre_address_1[pre_address_1.find(str_d) + len(str_d):]
        post_address = post_address[post_address.find(str_d) + len(str_d):]
        # 存数据库 同步更新patient
        image = Image(type=type, pre_address_1=pre_address_1, post_address=post_address, model_kind=model_kind,
                      patient_id=patient_id, operator_id=operator_id)
        db.session.add(image)
        db.session.flush()
        image_id = image.id
        Patient.query.filter_by(id=patient_id).update({
            'image_id': image_id,
            'last_time': db.func.now()
        })
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        traceback.print_exc()
        return {'success': False, 'msg': '处理图片时发生错误'}
    finally:
        # 最后删除原图片(模型种会额外保存一张，所以把当前这个删了)
        # os.remove(pre_path)
        pass
    return {'success': True, 'id': image_id}


# 执行多分辨率标注
@bp.route('/multi_transfer', methods=['POST'])
@login_required_ajax
def multi_transfer():
    form = ImageForm(request.form)
    pre_img_l = request.files.get('pre_img_l')
    pre_img_h = request.files.get('pre_img_h')
    if not form.validate():
        return {'success': False, 'msg': '数据格式有误，请检查后重试'}
    if not check_img(pre_img_l) and not check_img(pre_img_l):
        return {'success': False, 'msg': '图片有误，请检查后重试'}
    image_id = 0
    type = 2
    patient_id = form.patient_id.data
    model_kind = form.model_kind.data
    pre_path_l = save_img(pre_img_l)
    pre_path_h = save_img(pre_img_h)
    try:
        operator_id = g.user.id
        # pre_address_1, pre_address_2, post_address = d_pre(str(operator_id), str(patient_id), pre_path_l, pre_path_h)
        pre_address_1 = pre_path_l
        pre_address_2 = pre_path_h
        post_address = pre_path_h
        # 统一路径格式，方便下面截取
        pre_address_1 = pre_address_1.replace('\\', '/')
        pre_address_2 = pre_address_2.replace('\\', '/')
        post_address = post_address.replace('\\', '/')
        # 存数据库前把前缀删掉
        str_d = 'static/'
        pre_address_1 = pre_address_1[pre_address_1.find(str_d) + len(str_d):]
        pre_address_2 = pre_address_2[pre_address_2.find(str_d) + len(str_d):]
        post_address = post_address[post_address.find(str_d) + len(str_d):]
        # 数据库
        image = Image(type=type, pre_address_1=pre_address_1, pre_address_2=pre_address_2, post_address=post_address,
                      model_kind=model_kind, patient_id=patient_id, operator_id=operator_id)
        db.session.add(image)
        db.session.flush()
        image_id = image.id
        Patient.query.filter_by(id=patient_id).update({
            'image_id': image_id,
            'last_time': db.func.now()
        })
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        traceback.print_exc()
        return {'success': False, 'msg': '处理图片时发生错误'}
    finally:
        # 最后删除原图片(模型种会额外保存一张，所以把当前这个删了)
        # os.remove(pre_path_l)
        # os.remove(pre_path_h)
        pass
    return {'success': True, 'id': image_id}


# 用于页面中病人下拉框
def getPatientNameList():
    data_list = db.session.query(Patient.id, Patient.name).order_by(func.IF(func.ISNULL(Patient.last_time), 0, 1),
                                                                    Patient.last_time).all()
    patient_list = []
    for data in data_list:
        patient_list.append({
            'id': data.id,
            'name': data.name
        })
    return patient_list

# 检查图片格式
def check_img(img):
    if not img:
        return False
    # 将图片名按照 .  进行切分， 找到最后一个元素，也就是  文件的后缀名
    end_name = img.filename.rsplit('.')[-1]

    # 通过文件的后缀名判断 身份为 合法的  图片
    if end_name not in ['jpg', 'png', 'gif', 'jpeg']:
        return False
    return True

# 保存图片
def save_img(img):
    end_name = img.filename.rsplit('.')[-1]
    # 将 图片对象 存入 本地，然后将 路径 存入 数据库
    base_path = r'.\static\upload'
    filename = str(uuid4()) + '.' + end_name  # 为了生成一个不重复的 文件名
    img_path = os.path.join(base_path, filename)  # 将路径和文件名拼接在一起，方便保存文件

    img.save(img_path)  # 将图片对象保存到 本地

    return img_path
